<script setup lang="ts">
import type { FormInstance } from 'element-plus';

import type { Ref } from 'vue';

import type { TableSearchFormItem } from '#/components/data-table/types';

import { computed, defineProps, onMounted, onUnmounted, ref, watch } from 'vue';

// 定义组件 Props
interface Props {
    formItems?: TableSearchFormItem[];
    minItemWidth?: number;
    itemGap?: number; // 新增：项之间的间隔
}

const props = withDefaults(defineProps<Props>(), {
    formItems: () => [],
    minItemWidth: 280,
    itemGap: 16, // 默认间隔为16px
});

// 定义emits
// const emit = defineEmits<{
//     query: [formData: Record<string, any>];
//     reset: [];
// }>();

const form = defineModel<Record<string, any>>({ default: {} });
const show = ref(true);

// 获取容器DOM引用
const formContainer: Ref<HTMLElement | null> = ref(null);
const dataFormRef: Ref<FormInstance | null> = ref(null);

// 表单高度
const height = defineModel('height', { default: 0 });
// 折叠状态
const collapsed = defineModel<boolean | undefined>('collapsed', { default: undefined });
// 隐藏查询框数量
const hiddenCount = defineModel('hiddenCount', { default: 0 });

// 显示/隐藏查询表单
const onToggleVisible = (): boolean => {
    show.value = !show.value;
    return show.value;
};

// 当前列数
const currentColCount = ref(1);
// 计算是否需要显示折叠按钮
const isCollapsed = computed(() => {
    return props.formItems.length > currentColCount.value ? true : undefined;
});

// 计算可见的表单项
const visibleItems = computed(() => {
    if (!isCollapsed.value) {
        return props.formItems;
    }
    return collapsed.value ? props.formItems.slice(0, currentColCount.value) : props.formItems;
});

// 切换折叠状态
const onToggleCollapse = () => {
    collapsed.value = !collapsed.value;
};

// 计算列数的方法（考虑间隔宽度）
const calculateColumns = (): void => {
    if (!formContainer.value) return;

    height.value = formContainer.value.offsetHeight;

    const containerWidth = formContainer.value.offsetWidth;
    // 计算可用宽度（总宽度减去所有间隔）
    // 公式：(容器宽度 - (n-1)*间隔) / n >= 最小项宽度
    // 转换为：n <= (容器宽度 + 间隔) / (最小项宽度 + 间隔)
    let calculatedCols = Math.floor((containerWidth + props.itemGap) / (props.minItemWidth + props.itemGap));
    // 存在跨列的表单项时需要重新计算
    let c = 0;
    let h = 0;
    for (const element of props.formItems) {
        h++;
        c += element.span ?? 1;
        if (c >= calculatedCols) {
            calculatedCols = c > calculatedCols ? h - 1 : h;
            break;
        }
    }
    // 确保列数在合理范围内 (至少1列)
    currentColCount.value = Math.max(1, calculatedCols);
    // 计算隐藏的表单项数量
    hiddenCount.value = Math.max(props.formItems.length - currentColCount.value, 0);
};

// 防抖函数
const debounce = <T extends (...args: any[]) => any>(func: T, delay: number): ((...args: Parameters<T>) => void) => {
    let timeoutId: NodeJS.Timeout;
    return (...args: Parameters<T>) => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => func(...args), delay);
    };
};

// 防抖化的计算函数
const debouncedCalculate = debounce(calculateColumns, 150);

// ResizeObserver 实例
let resizeObserver: null | ResizeObserver = null;

// 生命周期钩子
onMounted(() => {
    calculateColumns(); // 初始计算
    window.addEventListener('resize', debouncedCalculate);

    // 监听容器宽度变化 (使用ResizeObserver)
    if (formContainer.value) {
        resizeObserver = new ResizeObserver(debouncedCalculate);
        resizeObserver.observe(formContainer.value);
    }
    collapsed.value = isCollapsed.value; // 存在折叠功能时，初始折叠状态为折叠
});

onUnmounted(() => {
    window.removeEventListener('resize', debouncedCalculate);

    if (resizeObserver) {
        resizeObserver.disconnect();
        resizeObserver = null;
    }
});

// 监听间隔和最小宽度变化，重新计算列数
watch(() => [props.itemGap, props.minItemWidth], debouncedCalculate);
// 监听折叠展示/隐藏状态变化，更新显示折叠按钮
watch(
    () => isCollapsed.value,
    (value) => {
        // undefined则表示当前查询条件不满足换行，折叠按钮可以不用展示
        // true则表示当前查询条件满足换行，此时如果是展开状态则需要折叠
        if (value === undefined || !collapsed.value) {
            collapsed.value = value;
        }
    },
);

// 修改handleReset以emit事件
const onReset = () => {
    dataFormRef.value?.resetFields();
};

defineExpose({
    onReset,
    onToggleCollapse,
    onToggleVisible,
});
</script>

<template>
    <div v-show="show" ref="formContainer" class="search-form-container">
        <!-- 动态渲染表单项 -->
        <el-form ref="dataFormRef" :model="form" label-position="left">
            <template v-for="item in visibleItems" :key="item.prop">
                <el-form-item v-if="!item.label" :prop="item.prop" v-show="false">
                    <el-input v-model="form[item.prop!!]" />
                </el-form-item>
            </template>
            <div
                class="grid w-full"
                :style="{
                    'grid-template-columns': `repeat(auto-fit, minmax(${props.minItemWidth}px, ${isCollapsed ? 1 : 0}fr))`,
                    gap: `${props.itemGap}px`,
                }"
            >
                <template v-for="item in visibleItems" :key="item.prop">
                    <el-form-item v-if="item.label" :key="item.prop" :label="item.label" :prop="item.prop" class="form-item" :style="`grid-column: span ${item.span}`">
                        <slot :name="item.prop" :form="form">
                            <el-input v-model="form[item.prop!!]" :placeholder="`请输入${item.label}`" clearable />
                        </slot>
                    </el-form-item>
                </template>
            </div>
        </el-form>
    </div>
</template>

<style scoped>
.search-form-container {
    position: relative;
}

/* 响应式设计：在小屏幕上调整按钮布局 */
@media (max-width: 640px) {
    /* 在小屏幕上让表单项全宽 */
    :deep(.form-item) {
        min-width: 100% !important;
    }
}
</style>
